home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / recov / recovFast.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  55KB  |  2,007 lines

  1. /* 
  2.  * recovFast.c --
  3.  *
  4.  *    The routines here deal with fast restart and recovery from an
  5.  *    area of memory preserved across crashes.
  6.  *
  7.  * Copyright 1987 Regents of the University of California
  8.  * All rights reserved.
  9.  */
  10.  
  11. #ifndef lint
  12. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/recov/recovFast.c,v 9.4 92/12/13 18:20:11 mgbaker Exp $ SPRITE (Berkeley)";
  13. #endif /* not lint */
  14.  
  15.  
  16. #include <sprite.h>
  17. #include <recov.h>
  18. #include <mach.h>
  19. #include <machConst.h>
  20. #include <sync.h>
  21. #include <stdio.h>
  22. #include <vm.h>
  23. #include <stdlib.h>
  24.  
  25. #define    NUM_RESTART_TYPES    10
  26.  
  27. /*
  28.  * Info per/object about what its checksum is, if it's allocated, or what
  29.  * the next free index is if it's not allocated.
  30.  */
  31. typedef    struct    ObjInfo {
  32.     short    applObjNum;
  33.     union    {
  34.     unsigned short    checksum;
  35.     unsigned short    nextFree;
  36.     } info;
  37. } ObjInfo;
  38.  
  39. /*
  40.  * Per-type information kept in the table of contents.  The objects for a type
  41.  * are stored as if in an array, indexed by the object's number.  The bitmap
  42.  * for a type shows the allocation of objects in the object array.  It also
  43.  * gives the application's object number for the object, if there is one.
  44.  * The value in the array for an object can be 0 (unallocated), or -1 (allocated
  45.  * without an application object number, or else give the application's
  46.  * object number.
  47.  */
  48. typedef struct    RestartTypeInfo {
  49.     int        objectSize;        /* Size of this type's objects. */
  50.     int        maxNumObjects;        /* Max possible objects at once. */
  51.     int        currentNum;        /* Current num of objects for type. */
  52.     int        applicationTypeID;    /* Application's type ID. */
  53.     int        firstFree;        /* First index in free obj buffer. */
  54.     ObjInfo    *objInfoAddr;        /* Address of checksum/free array. */
  55.     char    *objectsAddr;        /* Address of object storage. */
  56.     unsigned    short    (*Checksum)();    /* Function to use to generate checksum.
  57.                      * No checksum done if NIL. */
  58. } RestartTypeInfo;
  59.  
  60. typedef struct    RestartHeader {
  61.     int            initialized;
  62.     int            nextTypeID;
  63.     RestartTypeInfo    contents[NUM_RESTART_TYPES];
  64. } RestartHeader;
  65.  
  66.  
  67. RestartHeader    *restartTablePtr;
  68.  
  69. static    int    spaceUsed;
  70.  
  71. /*
  72.  * Used for saving past values of checksum routines for the different
  73.  * object types when the checksum is toggled on and off for testing.
  74.  */
  75. Address    checksumList[NUM_RESTART_TYPES] =
  76.     {(Address) NIL, (Address) NIL,
  77.     (Address) NIL, (Address) NIL,
  78.     (Address) NIL, (Address) NIL,
  79.     (Address) NIL, (Address) NIL,
  80.     (Address) NIL, (Address) NIL};
  81.  
  82. Boolean    recov_RestartDebug = FALSE;
  83.  
  84. static unsigned short GetFreeIndex _ARGS_((int typeID));
  85. static void AddFreeIndex _ARGS_((int typeID, int objNum));
  86.  
  87. static Sync_Lock restartTableLock;
  88. #define    LOCKPTR    (&restartTableLock)
  89.  
  90.  
  91. /*
  92.  *----------------------------------------------------------------------
  93.  *
  94.  * Recov_InitRecovBox --
  95.  *
  96.  *    Initialize fast recovery code.
  97.  *
  98.  * Results:
  99.  *    Whether or not box was already initialized.  (TRUE if done already.)
  100.  *
  101.  * Side effects:
  102.  *    Recovery area and data structures are initialized.
  103.  *
  104.  *----------------------------------------------------------------------
  105.  */
  106. Boolean
  107. Recov_InitRecovBox()
  108. {
  109.     Boolean    alreadyInit = FALSE;
  110.     int        nextID;
  111.  
  112.     restartTablePtr = (RestartHeader *) mach_RestartTablePtr;
  113.     if (recov_RestartDebug) {
  114.     printf("mach_RestartTablePtr is at 0x%x\n");
  115.     }
  116.     if (restartTablePtr == (RestartHeader *) NIL ||
  117.         restartTablePtr == (RestartHeader *) NULL) {
  118.     panic("Recov_InitRecovBox called with no restart table available.");
  119.     }
  120.     if ((Mach_GetRestartTableSize() & (VMMACH_PAGE_SIZE -1)) != 0) {
  121.     panic(
  122.     "Recov_Init_RecovBox: restart table not multiple of page size.\n");
  123.     }
  124.     if (((unsigned int) restartTablePtr & (VMMACH_PAGE_SIZE - 1)) != 0) {
  125.     panic(
  126.     "Recov_Init_RecovBox: restart table not aligned on page boundary.\n");
  127.     }
  128.     /*
  129.      * Check if we've been initialized before.
  130.      */
  131.     if (!restartTablePtr->initialized) {
  132.     /* Uninitialized - set everything to zero. */
  133.     bzero((char *) restartTablePtr, Mach_GetRestartTableSize());
  134.     spaceUsed = sizeof (RestartHeader);
  135.     if (recov_RestartDebug) {
  136.         printf("Recov_InitRecovBox: initialized, addr 0x%x.\n",
  137.             (char *) restartTablePtr);
  138.     }
  139.     } else {
  140.     alreadyInit = TRUE;
  141.     /* The nextTypeID is stored in table and needs no initialization. */
  142.     nextID = restartTablePtr->nextTypeID;
  143.     /* set spaceUsed */
  144.     if (nextID == 0) {
  145.         spaceUsed = 0;
  146.     } else {
  147.         spaceUsed = (unsigned int)
  148.             restartTablePtr->contents[nextID - 1].objectsAddr +
  149.             (restartTablePtr->contents[nextID - 1].maxNumObjects *
  150.             restartTablePtr->contents[nextID - 1].objectSize) -
  151.             (unsigned int) restartTablePtr;
  152.     }
  153.  
  154.     if (recov_RestartDebug) {
  155.         printf("Recov_InitRecovBox: already initialized, addr 0x%x.\n",
  156.             (char *) restartTablePtr);
  157.     }
  158.     }
  159.  
  160.     restartTablePtr->initialized = 1;
  161.  
  162.     return alreadyInit;
  163. }
  164.  
  165. /*
  166.  *----------------------------------------------------------------------
  167.  *
  168.  * Recov_ToggleChecksum --
  169.  *
  170.  *    Toggle whether checksum is done or not for type .
  171.  *
  172.  * Results:
  173.  *    Number of objects, given their size and the fact that there must be
  174.  *    a bitmap of their allocation, etc.
  175.  *
  176.  * Side effects:
  177.  *    None.
  178.  *
  179.  *----------------------------------------------------------------------
  180.  */
  181. void
  182. Recov_ToggleChecksum(typeID)
  183.     int        typeID;
  184. {
  185.     unsigned    short    (*save)();
  186.  
  187.     if (!recov_Transparent) {
  188.     printf("Recov_ToggleChecksum: no transparent recovery.\n");
  189.     return;
  190.     }
  191.     save = restartTablePtr->contents[typeID].Checksum;
  192.     restartTablePtr->contents[typeID].Checksum =
  193.         (unsigned short (*)()) checksumList[typeID];
  194.     checksumList[typeID] = (Address) save;
  195.     if (save != (unsigned short (*)()) NIL) {
  196.     printf("Checksum turned off.\n");
  197.     } else {
  198.     printf("Checksum turned on.\n");
  199.     }
  200.  
  201.     return;
  202. }
  203.  
  204.  
  205. /*
  206.  *----------------------------------------------------------------------
  207.  *
  208.  * GetFreeIndex --
  209.  *
  210.  *    Get the index of the next free object space. Take it off free list.
  211.  *
  212.  * Results:
  213.  *    The index of the free object space.
  214.  *
  215.  * Side effects:
  216.  *    Takes object off free list.
  217.  *
  218.  *----------------------------------------------------------------------
  219.  */
  220. static unsigned short
  221. GetFreeIndex(typeID)
  222.     int        typeID;
  223. {
  224.     unsigned short    freeIndex;
  225.     RestartTypeInfo    *typeInfoPtr;
  226.  
  227.     if (!recov_Transparent) {
  228.     panic("GetFreeIndex: no transparent recovery.");
  229.     }
  230.     typeInfoPtr = &(restartTablePtr->contents[typeID]);
  231.     freeIndex = typeInfoPtr->firstFree;
  232.     typeInfoPtr->firstFree = typeInfoPtr->objInfoAddr[freeIndex].info.nextFree;
  233.  
  234.     return freeIndex;
  235. }
  236.  
  237.  
  238. /*
  239.  *----------------------------------------------------------------------
  240.  *
  241.  * AddFreeIndex --
  242.  *
  243.  *    Add an object to the free list.
  244.  *
  245.  * Results:
  246.  *    None.
  247.  *
  248.  * Side effects:
  249.  *    Object goes at head of free list.
  250.  *
  251.  *----------------------------------------------------------------------
  252.  */
  253. static void
  254. AddFreeIndex(typeID, objNum)
  255.     int        typeID;
  256.     int        objNum;
  257. {
  258.     RestartTypeInfo    *typeInfoPtr;
  259.  
  260.     if (!recov_Transparent) {
  261.     panic("AddFreeIndex: no transparent recovery.");
  262.     }
  263.     typeInfoPtr = &(restartTablePtr->contents[typeID]);
  264.     typeInfoPtr->objInfoAddr[objNum].info.nextFree = typeInfoPtr->firstFree;
  265.     typeInfoPtr->firstFree = objNum;
  266.  
  267.     return;
  268. }
  269.  
  270.  
  271. /*
  272.  *----------------------------------------------------------------------
  273.  *
  274.  * Recov_MaxNumObjects --
  275.  *
  276.  *    Figure out how many objects of this new size can be put into the table.
  277.  *    If it's a fast restart, figure out how many total objects would fit
  278.  *    into the table assuming this is the first type.
  279.  *
  280.  * Results:
  281.  *    Number of objects, given their size and the fact that there must be
  282.  *    a bitmap of their allocation, etc.
  283.  *
  284.  * Side effects:
  285.  *    None.
  286.  *
  287.  *----------------------------------------------------------------------
  288.  */
  289. int
  290. Recov_MaxNumObjects(objectSize, restart)
  291.     int        objectSize;
  292.     Boolean    restart;    /* If this is a fast restart. */
  293. {
  294.     int        spaceLeft;
  295.     int        maxNumObjects;
  296.  
  297.     if (!recov_Transparent) {
  298.     printf("Recov_MaxNumObjects: no transparent recovery.\n");
  299.     return 0;
  300.     }
  301.     if (!restartTablePtr->initialized) {
  302.     panic("Recov_MaxNumObjects called before Recov_InitRecovBox.");
  303.     }
  304.     /*
  305.      * If this is a fast restart, spaceUsed includes everything in the table
  306.      * already and we'd get told we had room for almost no objects, but what
  307.      * we want on a fast restart is how many objects (old and new) the table
  308.      * will hold, so we do the calculation differently.  But this only works
  309.      * for the first type allocated after the restart!
  310.      */
  311.     if (restart) {
  312.     spaceLeft = Mach_GetRestartTableSize() - sizeof (RestartHeader);
  313.     } else {
  314.     spaceLeft = Mach_GetRestartTableSize() - spaceUsed;
  315.     }
  316.     /*
  317.      * This includes space for the objects and their checksum/freelist array
  318.      * and a word alignment.
  319.      */
  320.     maxNumObjects = (spaceLeft - sizeof (int)) / (objectSize + sizeof (int));
  321.  
  322.     return maxNumObjects;
  323. }
  324.  
  325. /*
  326.  *----------------------------------------------------------------------
  327.  *
  328.  * Recov_PrintSpace --
  329.  *
  330.  *    Print out how much space is taken by what in the recovery box.
  331.  *
  332.  * Results:
  333.  *    None.
  334.  *
  335.  * Side effects:
  336.  *    Prints out the result.
  337.  *
  338.  *----------------------------------------------------------------------
  339.  */
  340. void
  341. Recov_PrintSpace(objectSize)
  342.     int        objectSize;
  343. {
  344.     int        spaceLeft;
  345.     int        maxNumObjects;
  346.  
  347.     if (!recov_Transparent) {
  348.     printf("Recov_PrintSpace: no transparent recovery.\n");
  349.     return;
  350.     }
  351.     if (!restartTablePtr->initialized) {
  352.     panic("Recov_PrintSpace called before Recov_InitRecovBox.");
  353.     }
  354.     /*
  355.      */
  356.     printf("Sizes:\n");
  357.     printf("Header:\t%d\t0x%x\n", sizeof (RestartHeader),
  358.         sizeof (RestartHeader));
  359.     spaceLeft = Mach_GetRestartTableSize() - sizeof (RestartHeader);
  360.     printf("ObjSpace:\t%d\t0x%x\n", spaceLeft, spaceLeft);
  361.     spaceLeft = Mach_GetRestartTableSize() - spaceUsed;
  362.     printf("SpaceLeft:\t%d\t0x%x\n", spaceLeft, spaceLeft);
  363.     /*
  364.      * This includes space for the objects and their allocation bitmap
  365.      * and a word alignment.
  366.      */
  367.     maxNumObjects = (spaceLeft - sizeof (int)) / (objectSize + sizeof (int));
  368.     printf("This is room for %d (0x%x) objs of size %d with allocation map.\n",
  369.         maxNumObjects, maxNumObjects, objectSize);
  370.  
  371.     return;
  372. }
  373.  
  374.  
  375. /*
  376.  *----------------------------------------------------------------------
  377.  *
  378.  * Recov_InitType --
  379.  *
  380.  *    Initialize fast recovery area for a new object type.
  381.  *
  382.  * Results:
  383.  *    SUCCESS or FAILURE.  If successful we also return in objectTypeIDPtr
  384.  *    the type ID for this new object type if there are no errors, or
  385.  *    an error code (-1) if this does not work.  Reasons for failure are too
  386.  *    many object types already, not enough space for the desired number
  387.  *    of objects or an object size of zero, or else that the given
  388.  *    application type ID is positive (set) and turns out not to be unique.
  389.  *
  390.  * Side effects:
  391.  *    A portion of the recovery area is set aside.
  392.  *
  393.  *----------------------------------------------------------------------
  394.  */
  395. ReturnStatus
  396. Recov_InitType(objectSize, maxNumObjects, applicationTypeID, objectTypePtr,
  397. Checksum)
  398.     int            objectSize;
  399.     int            maxNumObjects;
  400.     int            applicationTypeID;
  401.     int            *objectTypePtr;    /* OUT: new object typeId
  402.                          * if successful. */
  403.     unsigned short    (*Checksum)();    /* No Checksum if 0 or NIL, use
  404.                      * default if == 1. */
  405. {
  406.     int            spaceLeft;
  407.     unsigned int    mask;
  408.     int            i;
  409.     RestartTypeInfo    *typeInfoPtr;
  410.     int            typeID;
  411.  
  412.     LOCK_MONITOR;
  413.  
  414.     if (recov_RestartDebug) {
  415.     printf("Recov_InitType: objectSize: %d, maxNumObjects: %d\n",
  416.         objectSize, maxNumObjects);
  417.     }
  418.  
  419.     if (!recov_Transparent) {
  420.     printf("Recov_InitType: no transparent recovery.\n");
  421.     UNLOCK_MONITOR;
  422.     return FAILURE;
  423.     }
  424.     
  425.     if (objectSize <= 0) {
  426.     printf("Recov_InitType: Cannot accept 0-sized object type.\n");
  427.     UNLOCK_MONITOR;
  428.     return FAILURE;
  429.     }
  430.  
  431.     /*
  432.      * Check if there are still slots for new object types.
  433.      */
  434.     *objectTypePtr = -1;
  435.     if (restartTablePtr->nextTypeID >= NUM_RESTART_TYPES) {
  436.     printf("Recov_InitType: No space for a new restart object type.\n");
  437.     UNLOCK_MONITOR;
  438.     return FAILURE;
  439.     }
  440.     typeID = restartTablePtr->nextTypeID;
  441.  
  442.     if (applicationTypeID > 0) {
  443.     for (i = 0; i < typeID; i++) {
  444.         if (restartTablePtr->contents[i].applicationTypeID ==
  445.             applicationTypeID) {
  446.         printf("Recov_InitType: applicationTypeID %d is not unique.\n",
  447.             applicationTypeID);
  448.         UNLOCK_MONITOR;
  449.         return FAILURE;
  450.         }
  451.     }
  452.     }
  453.     /*
  454.      * Check if there's space for the desired number of objects.
  455.      */
  456.     spaceLeft = Mach_GetRestartTableSize() - spaceUsed;
  457.     if (recov_RestartDebug) {
  458.     printf("Recov_InitType: space used: 0x%x, space left now: 0x%x\n",
  459.         spaceUsed, spaceLeft);
  460.     }
  461.  
  462.     /*
  463.      * Is there enough space for the new objects plus a bitmap
  464.      * of their allocation?  (Plus a word for alignment for the bitmap.)
  465.      */
  466.     if (Recov_MaxNumObjects(objectSize, 0) < maxNumObjects) {
  467.     printf("Recov_InitType: Not enough space left for request.\n");
  468.     UNLOCK_MONITOR;
  469.     return FAILURE;
  470.     }
  471.     
  472.     /*
  473.      * Allocate new object type space.
  474.      */
  475.     typeInfoPtr = &(restartTablePtr->contents[typeID]);
  476.     typeInfoPtr->objectSize = objectSize;
  477.     typeInfoPtr->applicationTypeID = applicationTypeID;
  478.     typeInfoPtr->maxNumObjects = maxNumObjects;
  479.     typeInfoPtr->currentNum = 0;
  480.     typeInfoPtr->objInfoAddr = (ObjInfo *) (((char *) restartTablePtr) +
  481.         spaceUsed + sizeof (int));
  482.     /* Word-align the checksum/freelist array. */
  483.     mask = sizeof (int) - 1;
  484.     typeInfoPtr->objInfoAddr = (ObjInfo *)
  485.         (((unsigned int) typeInfoPtr->objInfoAddr) & ~mask);
  486.     typeInfoPtr->objectsAddr = (char *)
  487.         (((char *) typeInfoPtr->objInfoAddr) +
  488.         (maxNumObjects * sizeof (ObjInfo)));
  489.  
  490.     if (recov_RestartDebug) {
  491.     printf("Recov_InitType: objInfoAddr: 0x%x, objectsAddr: 0x%x\n",
  492.         typeInfoPtr->objInfoAddr, typeInfoPtr->objectsAddr);
  493.     }
  494.     
  495.     spaceUsed = (unsigned int) typeInfoPtr->objectsAddr +
  496.         (maxNumObjects * objectSize) - (unsigned int) restartTablePtr;
  497.     if (Checksum == (unsigned short (*)()) 0) {
  498.     typeInfoPtr->Checksum = (unsigned short (*)()) NIL;
  499.     } else if (Checksum == (unsigned short (*)()) 1) {
  500.     typeInfoPtr->Checksum = Recov_Checksum;
  501.     } else {
  502.     typeInfoPtr->Checksum = Checksum;
  503.     }
  504.  
  505.     /* Set up free list. */
  506.     typeInfoPtr->firstFree = 0;
  507.     for (i = 0; i < maxNumObjects - 1; i++) {
  508.     typeInfoPtr->objInfoAddr[i].info.nextFree = i + 1;
  509.     }
  510.     /* Point back to beginning of array. */
  511.     typeInfoPtr->objInfoAddr[maxNumObjects - 1].info.nextFree = 0;
  512.  
  513.     *objectTypePtr = typeID;
  514.  
  515.     if (recov_RestartDebug) {
  516.     printf("Recov_InitType: new object type %d\n", *objectTypePtr);
  517.     }
  518.     restartTablePtr->nextTypeID++;
  519.     
  520.     UNLOCK_MONITOR;
  521.     return SUCCESS;
  522. }
  523.  
  524.  
  525. /*
  526.  *----------------------------------------------------------------------
  527.  *
  528.  * Recov_GetObjectSize --
  529.  *
  530.  *    Return the object size for a given type of objects.
  531.  *
  532.  * Results:
  533.  *    The size of an object of the given type. -1 if there is no such
  534.  *    type.
  535.  *
  536.  * Side effects:
  537.  *    None.
  538.  *
  539.  *----------------------------------------------------------------------
  540.  */
  541. int
  542. Recov_GetObjectSize(typeID)
  543.     int        typeID;        /* Type of object to insert. */
  544. {
  545.     int        objectSize;
  546.  
  547.     LOCK_MONITOR;
  548.     if (!recov_Transparent) {
  549.     printf("Recov_GetObjectSize: no transparent recovery.\n");
  550.     UNLOCK_MONITOR;
  551.     return -1;
  552.     }
  553.     if (typeID < 0 || typeID >= restartTablePtr->nextTypeID) {
  554.     UNLOCK_MONITOR;
  555.     return -1;
  556.     }
  557.  
  558.     objectSize = restartTablePtr->contents[typeID].objectSize;
  559.     UNLOCK_MONITOR;
  560.     return objectSize;
  561. }
  562.  
  563.  
  564. /*
  565.  *----------------------------------------------------------------------
  566.  *
  567.  * Recov_InsertObject --
  568.  *
  569.  *    Insert an object into the recovery area.
  570.  *
  571.  * Results:
  572.  *    SUCCESS or FAILURE.  Reasons for failure are that the object type
  573.  *    doesn't exist or that the area for this object type is already
  574.  *    filled.
  575.  *
  576.  * Side effects:
  577.  *    If successful, a new object is recorded in the recovery area.
  578.  *
  579.  *----------------------------------------------------------------------
  580.  */
  581. ReturnStatus
  582. Recov_InsertObject(typeID, objectPtr, applicationObjectNum, objectIDPtr)
  583.     int            typeID;        /* Type of object to insert. */
  584.     ClientData        objectPtr;    /* The object. */
  585.     int            applicationObjectNum;    /* The appl's number for obj. */
  586.     Recov_ObjectID    *objectIDPtr;    /* OUT: ID of new object. */
  587. {
  588.     int            i;
  589.     RestartTypeInfo    *restartTypeInfoPtr;
  590.     ObjInfo        *objInfoAddr;
  591.     int            objectSize;
  592.     char        *addr;
  593.     int            freeIndex;
  594.  
  595.     LOCK_MONITOR;
  596.  
  597.     objectIDPtr->typeID = -1;
  598.     objectIDPtr->objectNumber = -1;
  599.  
  600.     if (!recov_Transparent) {
  601.     printf("Recov_InsertObject: no transparent recovery.\n");
  602.     UNLOCK_MONITOR;
  603.     return FAILURE;
  604.     }
  605.     if (typeID < 0 || typeID >= restartTablePtr->nextTypeID) {
  606.     printf("Recov_InsertObject: No such fast restart object type.\n");
  607.     UNLOCK_MONITOR;
  608.     return FAILURE;
  609.     }
  610.     restartTypeInfoPtr = &(restartTablePtr->contents[typeID]);
  611.     if (restartTypeInfoPtr->currentNum >=
  612.         restartTypeInfoPtr->maxNumObjects) {
  613.     printf("Recov_InsertObject: No space for another such object.\n");
  614.     UNLOCK_MONITOR;
  615.     return FAILURE;
  616.     }
  617.  
  618.     /* Get a free index. */
  619.     freeIndex = GetFreeIndex(typeID);
  620.  
  621.     objInfoAddr = restartTypeInfoPtr->objInfoAddr;
  622.     if (applicationObjectNum <= 0) {
  623.     objInfoAddr[freeIndex].applObjNum = -1;
  624.     } else {
  625.     /* Should I really check?  This will make it a lot slower. */
  626.     for (i = 0; i < restartTypeInfoPtr->maxNumObjects; i++) {
  627.         if (objInfoAddr[i].applObjNum == applicationObjectNum) {
  628.         printf("Recov_InsertObject: Object num already used.\n");
  629.         UNLOCK_MONITOR;
  630.         return FAILURE;
  631.         }
  632.     }
  633.     objInfoAddr[freeIndex].applObjNum = applicationObjectNum;
  634.     }
  635.  
  636.     objectSize = restartTypeInfoPtr->objectSize;
  637.     addr = restartTypeInfoPtr->objectsAddr + (freeIndex * objectSize);
  638.  
  639.     if (restartTypeInfoPtr->Checksum != (unsigned short (*)()) NIL) {
  640.     volatile unsigned short    sum;
  641.     /* Volatile should change when we check the checksum!!! */
  642.  
  643.     sum = (*(restartTypeInfoPtr->Checksum))(objectSize,
  644.         (Address) objectPtr);
  645.     }
  646.  
  647.     objectIDPtr->typeID = typeID;
  648.     objectIDPtr->objectNumber = freeIndex;
  649.     restartTypeInfoPtr->currentNum++;
  650.  
  651.     bcopy((char *) objectPtr, addr, objectSize);
  652.     
  653.  
  654.     UNLOCK_MONITOR;
  655.     return SUCCESS;
  656. }
  657.  
  658.  
  659. /*
  660.  *----------------------------------------------------------------------
  661.  *
  662.  * Recov_InsertObjects --
  663.  *
  664.  *    Insert a set of objects into the recovery area at once.  If the
  665.  *    objNumBuffer is not NIL, then this array gives the application's
  666.  *    object numbers to record.
  667.  *
  668.  * Results:
  669.  *    SUCCESS or FAILURE.  Reasons for failure are that the object type
  670.  *    doesn't exist or that the area for this object type is already
  671.  *    filled.  The objects' IDs are returned in the out-going buffer.
  672.  *
  673.  * Side effects:
  674.  *    If successful, new objects are recorded in the recovery area.
  675.  *    If the routine returns SUCCESS, then all the objects have been
  676.  *    inserted.  If it returns FAILURE, then no objects have been inserted.
  677.  *    If it panics, then the results are undefined.
  678.  *    
  679.  *
  680.  *----------------------------------------------------------------------
  681.  */
  682. ReturnStatus
  683. Recov_InsertObjects(typeID, numObjs, obuffer, objNumBuffer, objIDBuffer)
  684.     int            typeID;        /* Type of object to insert. */
  685.     int            numObjs;    /* Number of objects to insert. */
  686.     char        *obuffer;    /* The objects. */
  687.     int            *objNumBuffer;    /* The appl's numbers for objs. */
  688.     Recov_ObjectID    *objIDBuffer;    /* OUT: IDs of new objects. */
  689. {
  690.     int            i, freeIndex;
  691.     RestartTypeInfo    *restartTypeInfoPtr;
  692.     ObjInfo        *objInfoAddr;
  693.     int            objectSize;
  694.     char        *addr;
  695.     Recov_ObjectID    *objectIDPtr;
  696.     char        *objectPtr;
  697.  
  698.     LOCK_MONITOR;
  699.  
  700.     if (!recov_Transparent) {
  701.     printf("Recov_InsertObjects: no transparent recovery.\n");
  702.     UNLOCK_MONITOR;
  703.     return FAILURE;
  704.     }
  705.  
  706.     /* Should I bother to do this? */
  707.     for (i = 0; i < numObjs; i++) {
  708.     objIDBuffer[i].typeID = -1;
  709.     objIDBuffer[i].objectNumber = -1;
  710.     }
  711.  
  712.     if (typeID < 0 || typeID >= restartTablePtr->nextTypeID) {
  713.     printf("Recov_InsertObjects: No such fast restart object type.\n");
  714.     UNLOCK_MONITOR;
  715.     return FAILURE;
  716.     }
  717.     restartTypeInfoPtr = &(restartTablePtr->contents[typeID]);
  718.     if (restartTypeInfoPtr->currentNum + numObjs >
  719.         restartTypeInfoPtr->maxNumObjects) {
  720.     printf("Recov_InsertObjects: Not enough space for new objects.\n");
  721.     UNLOCK_MONITOR;
  722.     return FAILURE;
  723.     }
  724.  
  725.     objInfoAddr = restartTypeInfoPtr->objInfoAddr;
  726.  
  727.     if (objNumBuffer != (int *) NIL) {
  728.     /* Should I really check?  This will make it a lot slower. */
  729.     for (i = 0; i < numObjs; i++) {
  730.         for (i = 0; i < restartTypeInfoPtr->maxNumObjects; i++) {
  731.         if (objInfoAddr[i].applObjNum == objNumBuffer[i]) {
  732.             printf("Recov_InsertObjects: Object num %d already used.\n",
  733.                 objNumBuffer[i]);
  734.             UNLOCK_MONITOR;
  735.             return FAILURE;
  736.         }
  737.         }
  738.     }
  739.     }
  740.  
  741.     objectSize = restartTypeInfoPtr->objectSize;
  742.     /* Get first empty slot. */
  743.     freeIndex = GetFreeIndex(typeID);
  744.  
  745.     for (i = 0; i < numObjs; i++) {
  746.     if (objNumBuffer != (int *) NIL) {
  747.         objInfoAddr[freeIndex].applObjNum = objNumBuffer[i];
  748.     } else {
  749.         objInfoAddr[freeIndex].applObjNum = -1;
  750.     }
  751.     objectIDPtr = &(objIDBuffer[i]);
  752.     objectIDPtr->typeID = typeID;
  753.     objectIDPtr->objectNumber = freeIndex;
  754.     restartTypeInfoPtr->currentNum++;
  755.  
  756.     objectPtr = obuffer + (objectSize * i);
  757.     addr = restartTypeInfoPtr->objectsAddr + (freeIndex * objectSize);
  758.  
  759.     if (restartTypeInfoPtr->Checksum != (unsigned short (*)()) NIL) {
  760.         volatile unsigned short    sum;
  761.         /* Volatile should change when we check the checksum!!! */
  762.  
  763.         sum = (*(restartTypeInfoPtr->Checksum))(objectSize,
  764.             (Address) objectPtr);
  765.     }
  766.  
  767.     bcopy((char *) objectPtr, addr, objectSize);
  768.     /* Find next empty slot. */
  769.     freeIndex = GetFreeIndex(typeID);
  770.     }
  771.  
  772.     UNLOCK_MONITOR;
  773.     return SUCCESS;
  774. }
  775.  
  776.  
  777. /*
  778.  *----------------------------------------------------------------------
  779.  *
  780.  * Recov_DeleteObject --
  781.  *
  782.  *    Delete an object from the recovery area.
  783.  *
  784.  * Results:
  785.  *    SUCCESS or FAILURE.  Reasons for failure are that the object type
  786.  *    doesn't exist or that the object doesn't exist.
  787.  *
  788.  * Side effects:
  789.  *    If successful, an object space is freed up.
  790.  *
  791.  *----------------------------------------------------------------------
  792.  */
  793. ReturnStatus
  794. Recov_DeleteObject(objectID)
  795.     Recov_ObjectID    objectID;    /* ID of object to remove. */
  796. {
  797.     ObjInfo        *objInfoAddr;
  798.     char        *addr;
  799.     int            objectSize;
  800.     RestartTypeInfo    *restartTypeInfoPtr;
  801.  
  802.     LOCK_MONITOR;
  803.  
  804.     if (!recov_Transparent) {
  805.     printf("Recov_DeleteObject: no transparent recovery.\n");
  806.     UNLOCK_MONITOR;
  807.     return FAILURE;
  808.     }
  809.     restartTypeInfoPtr =
  810.         &(restartTablePtr->contents[objectID.typeID]);
  811.     if (objectID.typeID < 0 || objectID.typeID >= restartTablePtr->nextTypeID) {
  812.     printf("Recov_DeleteObject: bad typeID.\n");
  813.     UNLOCK_MONITOR;
  814.     return FAILURE;
  815.     }
  816.     if (objectID.objectNumber < 0 ||
  817.         objectID.objectNumber > restartTypeInfoPtr->maxNumObjects) {
  818.     printf("Recov_DeleteObject: bad object number.\n");
  819.     UNLOCK_MONITOR;
  820.     return FAILURE;
  821.     }
  822.     if (restartTypeInfoPtr->objectSize <= 0) {
  823.     printf("Recov_DeleteObject: bad object type.\n");
  824.     UNLOCK_MONITOR;
  825.     return FAILURE;
  826.     }
  827.     objInfoAddr = restartTypeInfoPtr->objInfoAddr;
  828.     if (objInfoAddr[objectID.objectNumber].applObjNum == 0) {
  829.     printf("Recov_DeleteObject: object doesn't exist.\n");
  830.     UNLOCK_MONITOR;
  831.     return FAILURE;
  832.     }
  833.     objInfoAddr[objectID.objectNumber].applObjNum = 0;
  834.     AddFreeIndex(objectID.typeID, objectID.objectNumber);
  835.     objectSize = restartTypeInfoPtr->objectSize;
  836.     restartTypeInfoPtr->currentNum--;
  837.     if (restartTypeInfoPtr->currentNum < 0) {
  838.     UNLOCK_MONITOR;
  839.     panic("Recov_DeleteObject: less than zero objects of a type.\n");
  840.     }
  841.     addr = restartTypeInfoPtr->objectsAddr +
  842.         (objectID.objectNumber * objectSize);
  843.     /* Not really necessary, but helpful for debugging. */
  844.     bzero(addr, objectSize);
  845.  
  846.     UNLOCK_MONITOR;
  847.     return SUCCESS;
  848. }
  849.  
  850. /*
  851.  *----------------------------------------------------------------------
  852.  *
  853.  * Recov_UpdateObject --
  854.  *
  855.  *    Update an object in the recovery area.
  856.  *
  857.  * Results:
  858.  *    SUCCESS or FAILURE.  Reasons for failure are that the object type
  859.  *    doesn't exist or that the object doesn't exist.
  860.  *
  861.  * Side effects:
  862.  *    If successful, an object is updated.
  863.  *
  864.  *----------------------------------------------------------------------
  865.  */
  866. ReturnStatus
  867. Recov_UpdateObject(objectPtr, objectID)
  868.     ClientData        objectPtr;    /* New value of object. */
  869.     Recov_ObjectID    objectID;    /* ID of object to update. */
  870. {
  871.     ObjInfo        *objInfoAddr;
  872.     char        *addr;
  873.     RestartTypeInfo    *restartTypeInfoPtr;
  874.     int            objectSize;
  875.  
  876.     LOCK_MONITOR;
  877.  
  878.     if (!recov_Transparent) {
  879.     printf("Recov_UpdateObject: no transparent recovery.\n");
  880.     UNLOCK_MONITOR;
  881.     return FAILURE;
  882.     }
  883.     restartTypeInfoPtr =
  884.         &(restartTablePtr->contents[objectID.typeID]);
  885.     if (objectID.typeID < 0 || objectID.typeID >= restartTablePtr->nextTypeID) {
  886.     printf("Recov_UpdateObject: bad typeID.\n");
  887.     UNLOCK_MONITOR;
  888.     return FAILURE;
  889.     }
  890.     if (objectID.objectNumber < 0 ||
  891.         objectID.objectNumber > restartTypeInfoPtr->maxNumObjects) {
  892.     printf("Recov_UpdateObject: bad object number.\n");
  893.     UNLOCK_MONITOR;
  894.     return FAILURE;
  895.     }
  896.     if (restartTypeInfoPtr->objectSize <= 0) {
  897.     printf("Recov_UpdateObject: bad object type.\n");
  898.     UNLOCK_MONITOR;
  899.     return FAILURE;
  900.     }
  901.     objInfoAddr = restartTypeInfoPtr->objInfoAddr;
  902.     if (objInfoAddr[objectID.objectNumber].applObjNum == 0) {
  903.     printf("Recov_UpdateObject: object doesn't exist.\n");
  904.     UNLOCK_MONITOR;
  905.     return FAILURE;
  906.     }
  907.     objectSize = restartTypeInfoPtr->objectSize;
  908.     addr = restartTypeInfoPtr->objectsAddr +
  909.         (objectID.objectNumber * objectSize);
  910.  
  911.     if (restartTypeInfoPtr->Checksum != (unsigned short (*)()) NIL) {
  912.     volatile unsigned short    sum;
  913.     /* XXX Volatile should change when we check the checksum!!! */
  914.  
  915.     sum = (*(restartTypeInfoPtr->Checksum))(objectSize,
  916.         (Address) objectPtr);
  917.     }
  918.  
  919.     bcopy((char *) objectPtr, addr, objectSize);
  920.  
  921.     UNLOCK_MONITOR;
  922.     return SUCCESS;
  923. }
  924.  
  925. /*
  926.  *----------------------------------------------------------------------
  927.  *
  928.  * Recov_ReturnObject --
  929.  *
  930.  *    Return the value of a single object.
  931.  *
  932.  * Results:
  933.  *    SUCCESS or FAILURE.  Reasons for failure are that the object type
  934.  *    doesn't exist or that the object doesn't exist.
  935.  *
  936.  * Side effects:
  937.  *    If successful, an object is returned.
  938.  *
  939.  *----------------------------------------------------------------------
  940.  */
  941. ReturnStatus
  942. Recov_ReturnObject(objectPtr, objectID, checksum)
  943.     ClientData        objectPtr;    /* Ptr to return object. */
  944.     Recov_ObjectID    objectID;    /* ID of object to return. */
  945.     Boolean        checksum;
  946. {
  947.     ObjInfo        *objInfoAddr;
  948.     char        *addr;
  949.     RestartTypeInfo    *restartTypeInfoPtr;
  950.     int            objectSize;
  951.  
  952.     LOCK_MONITOR;
  953.  
  954.     if (!recov_Transparent) {
  955.     printf("Recov_ReturnObject: no transparent recovery.\n");
  956.     UNLOCK_MONITOR;
  957.     return FAILURE;
  958.     }
  959.     restartTypeInfoPtr =
  960.         &(restartTablePtr->contents[objectID.typeID]);
  961.     if (objectID.typeID < 0 || objectID.typeID >= restartTablePtr->nextTypeID) {
  962.     printf("Recov_ReturnObject: bad typeID.\n");
  963.     UNLOCK_MONITOR;
  964.     return FAILURE;
  965.     }
  966.     if (objectID.objectNumber < 0 ||
  967.         objectID.objectNumber > restartTypeInfoPtr->maxNumObjects) {
  968.     printf("Recov_ReturnObject: bad object number.\n");
  969.     UNLOCK_MONITOR;
  970.     return FAILURE;
  971.     }
  972.     if (restartTypeInfoPtr->objectSize <= 0) {
  973.     printf("Recov_ReturnObject: bad object type.\n");
  974.     UNLOCK_MONITOR;
  975.     return FAILURE;
  976.     }
  977.     objInfoAddr = restartTypeInfoPtr->objInfoAddr;
  978.     if (objInfoAddr[objectID.objectNumber].applObjNum == 0) {
  979.     printf("Recov_ReturnObject: object doesn't exist.\n");
  980.     UNLOCK_MONITOR;
  981.     return FAILURE;
  982.     }
  983.     objectSize = restartTypeInfoPtr->objectSize;
  984.     addr = restartTypeInfoPtr->objectsAddr +
  985.         (objectID.objectNumber * objectSize);
  986.  
  987.     if (checksum && restartTypeInfoPtr->Checksum !=
  988.         (unsigned short (*)()) NIL) {
  989.     volatile unsigned short    sum;
  990.     /* XXX Volatile should change when we check the checksum!!! */
  991.  
  992.     sum = (*(restartTypeInfoPtr->Checksum))(objectSize, (Address) addr);
  993.     }
  994.     bcopy(addr, (char *) objectPtr, objectSize);
  995.  
  996.     UNLOCK_MONITOR;
  997.     return SUCCESS;
  998. }
  999.  
  1000. /*
  1001.  *----------------------------------------------------------------------
  1002.  *
  1003.  * Recov_ReturnObjects --
  1004.  *
  1005.  *    Return an array of all the objects of a particular type.  Also return
  1006.  *    an array of their object IDs if the id buffer is not NIL.  Finally,
  1007.  *    return an array of the corresponding application object numbers if the
  1008.  *    application num buffer is not NIL.
  1009.  *
  1010.  * Results:
  1011.  *    SUCCESS or FAILURE.  Reasons for failure are that the object type
  1012.  *    doesn't exist or that not enough space was handed to the routine.
  1013.  *    The lengthPtrs return the actual length of the buffers filled in.
  1014.  *
  1015.  * Side effects:
  1016.  *    If successful, an array of objects is returned in the object buffer
  1017.  *    and an array of object IDs in the object ID buffer (if not NIL),
  1018.  *    and an array of application's object numbers in the application object
  1019.  *    num buffer (if not NIL).
  1020.  *
  1021.  *----------------------------------------------------------------------
  1022.  */
  1023. ReturnStatus
  1024. Recov_ReturnObjects(typeID, olengthPtr, obuffer, ilengthPtr, ibuffer,
  1025.     alengthPtr, abuffer)
  1026.     int        typeID;        /* Type of objects to return. */
  1027.     int        *olengthPtr;    /* IN/OUT: length of object buffer. */
  1028.     char    *obuffer;    /* OUT: Buffer to put objects into. */
  1029.     int        *ilengthPtr;    /* IN/OUT: length of object ID buffer. */
  1030.     char    *ibuffer;    /* OUT: Buffer to put object IDs into. */
  1031.     int        *alengthPtr;    /* IN/OUT: length of appl. obj. num buffer. */
  1032.     char    *abuffer;    /* OUT: Buffer to put appl. obj. nums into. */
  1033. {
  1034.     ObjInfo        *objInfoAddr;
  1035.     char        *addr;
  1036.     RestartTypeInfo    *restartTypeInfoPtr;
  1037.     int            i;
  1038.     int            destNum;
  1039.     int            osizeNeeded;
  1040.     int            isizeNeeded = 0;
  1041.     int            asizeNeeded = 0;
  1042.  
  1043.     LOCK_MONITOR;
  1044.  
  1045.     if (!recov_Transparent) {
  1046.     printf("Recov_ReturnObjects: no transparent recovery.\n");
  1047.     UNLOCK_MONITOR;
  1048.     return FAILURE;
  1049.     }
  1050.     restartTypeInfoPtr =
  1051.         &(restartTablePtr->contents[typeID]);
  1052.     if (typeID < 0 || typeID >= restartTablePtr->nextTypeID) {
  1053.     printf("Recov_ReturnObjects: bad typeID.\n");
  1054.     UNLOCK_MONITOR;
  1055.     return FAILURE;
  1056.     }
  1057.     if (restartTypeInfoPtr->objectSize <= 0) {
  1058.     printf("Recov_ReturnObjects: bad object type.\n");
  1059.     UNLOCK_MONITOR;
  1060.     return FAILURE;
  1061.     }
  1062.     osizeNeeded = restartTypeInfoPtr->currentNum *
  1063.         restartTypeInfoPtr->objectSize;
  1064.     if (*olengthPtr < osizeNeeded) {
  1065.     printf("Recov_ReturnObjects: not enough space in object buffer.\n");
  1066.     *olengthPtr = osizeNeeded;
  1067.     UNLOCK_MONITOR;
  1068.     return FAILURE;
  1069.     }
  1070.     if (ibuffer != (char *) NIL) {
  1071.     isizeNeeded = restartTypeInfoPtr->currentNum *
  1072.         sizeof (Recov_ObjectID);
  1073.     if (*ilengthPtr < isizeNeeded) {
  1074.         printf("Recov_ReturnObjects: not enough space in id buffer.\n");
  1075.         *ilengthPtr = isizeNeeded;
  1076.         UNLOCK_MONITOR;
  1077.         return FAILURE;
  1078.     }
  1079.     }
  1080.     if (abuffer != (char *) NIL) {
  1081.     asizeNeeded = restartTypeInfoPtr->currentNum * sizeof (int);
  1082.     if (*alengthPtr < asizeNeeded) {
  1083.     printf("Recov_ReturnObjects: not enough space in appl. num buffer.\n");
  1084.         *alengthPtr = asizeNeeded;
  1085.         UNLOCK_MONITOR;
  1086.         return FAILURE;
  1087.     }
  1088.     }
  1089.     bzero(obuffer, *olengthPtr);    /* Easier debugging if all bzeroed. */
  1090.     *olengthPtr = osizeNeeded;
  1091.     if (ibuffer != (char *) NIL) {
  1092.     bzero(ibuffer, *ilengthPtr);
  1093.     *ilengthPtr = isizeNeeded;
  1094.     }
  1095.     if (abuffer != (char *) NIL) {
  1096.     bzero(abuffer, *alengthPtr);
  1097.     *alengthPtr = asizeNeeded;
  1098.     }
  1099.  
  1100.  
  1101.     objInfoAddr = restartTypeInfoPtr->objInfoAddr;
  1102.     destNum = 0;
  1103.     addr = restartTypeInfoPtr->objectsAddr;
  1104.     for (i = 0; i < restartTypeInfoPtr->maxNumObjects; i++) {
  1105.     if (objInfoAddr[i].applObjNum != 0) {
  1106.         
  1107.         if (restartTypeInfoPtr->Checksum != (unsigned short (*)()) NIL) {
  1108.         volatile unsigned short    sum;
  1109.         /* Volatile should change when we check the checksum!!! */
  1110.  
  1111.         sum = (*(restartTypeInfoPtr->Checksum))
  1112.             (restartTypeInfoPtr->objectSize, (Address) addr);
  1113.         }
  1114.  
  1115.         /* copy object */
  1116.         bcopy(addr, obuffer + (destNum * restartTypeInfoPtr->objectSize),
  1117.             restartTypeInfoPtr->objectSize);
  1118.         if (ibuffer != (char *) NIL) {
  1119.         ((Recov_ObjectID *) ibuffer)[destNum].typeID = typeID;
  1120.         ((Recov_ObjectID *) ibuffer)[destNum].objectNumber = i;
  1121.         }
  1122.         if (abuffer != (char *) NIL) {
  1123.         ((int *) abuffer)[destNum] = objInfoAddr[i].applObjNum;
  1124.         }
  1125.         destNum++;
  1126.     }
  1127.     addr += restartTypeInfoPtr->objectSize;
  1128.     }
  1129.     if (destNum > restartTypeInfoPtr->currentNum) {
  1130.     UNLOCK_MONITOR;
  1131.     panic("Recov_ReturnObjects: miscalculation of number of objects.");
  1132.     }
  1133.  
  1134.     UNLOCK_MONITOR;
  1135.     return SUCCESS;
  1136. }
  1137.  
  1138. /*
  1139.  *----------------------------------------------------------------------
  1140.  *
  1141.  * Recov_ReturnContents --
  1142.  *
  1143.  *    Return the table of contents.
  1144.  *
  1145.  * Results:
  1146.  *    SUCCESS or FAILURE.  The procedure can return failure if not enough
  1147.  *    buffer space is passed to it.
  1148.  *
  1149.  * Side effects:
  1150.  *    If successful, the table of contents is copied into the out param.
  1151.  *    The lengthPtr is filled in with the needed length of the buffer on
  1152.  *    both SUCCESS and FAILURE.
  1153.  *
  1154.  *----------------------------------------------------------------------
  1155.  */
  1156. ReturnStatus
  1157. Recov_ReturnContents(lengthPtr, buffer)
  1158.     int        *lengthPtr;    /* IN/OUT: length of buffer. */
  1159.     char    *buffer;    /* OUT: Buffer to put table into. */
  1160. {
  1161.     int            i;
  1162.     int            sizeNeeded;
  1163.     Recov_ContentsEntry *bufPtr;
  1164.     RestartTypeInfo    *restartTypeInfoPtr;
  1165.  
  1166.     LOCK_MONITOR;
  1167.  
  1168.     if (!recov_Transparent) {
  1169.     printf("Recov_ReturnContents: no transparent recovery.\n");
  1170.     UNLOCK_MONITOR;
  1171.     return FAILURE;
  1172.     }
  1173.     for (i = 0; i < NUM_RESTART_TYPES; i++) {
  1174.     if (restartTablePtr->contents[i].objectSize <= 0) {
  1175.         break;
  1176.     }
  1177.     }
  1178.     sizeNeeded = i * sizeof (Recov_ContentsEntry);
  1179.     if (sizeNeeded > *lengthPtr) {
  1180.     *lengthPtr = sizeNeeded;
  1181.     printf("Recov_ReturnContents: not enough buffer space.\n");
  1182.     UNLOCK_MONITOR;
  1183.     return FAILURE;
  1184.     }
  1185.     *lengthPtr = sizeNeeded;
  1186.  
  1187.     bufPtr = (Recov_ContentsEntry *) buffer;
  1188.     for (i = 0; i < NUM_RESTART_TYPES; i++) {
  1189.     if (restartTablePtr->contents[i].objectSize <= 0) {
  1190.         break;
  1191.     }
  1192.     restartTypeInfoPtr = &(restartTablePtr->contents[i]);
  1193.     bufPtr->objectSize = restartTypeInfoPtr->objectSize;
  1194.     bufPtr->maxNumObjects = restartTypeInfoPtr->maxNumObjects;
  1195.     bufPtr->applicationTypeID =
  1196.         restartTypeInfoPtr->applicationTypeID;
  1197.     bufPtr->currentNum = restartTypeInfoPtr->currentNum;
  1198.     bufPtr->firstFree = restartTypeInfoPtr->firstFree;
  1199.     bufPtr++;
  1200.     }
  1201.  
  1202.  
  1203.     UNLOCK_MONITOR;
  1204.     return SUCCESS;
  1205. }
  1206.  
  1207. /*
  1208.  *----------------------------------------------------------------------
  1209.  *
  1210.  * Recov_NumObjects --
  1211.  *
  1212.  *    Return the current number of objects for given type.
  1213.  *
  1214.  * Results:
  1215.  *    The number, or -1 if something went wrong.
  1216.  *
  1217.  * Side effects:
  1218.  *    None.
  1219.  *
  1220.  *----------------------------------------------------------------------
  1221.  */
  1222. int
  1223. Recov_NumObjects(typeID)
  1224.     int        typeID;    /* IN: type of object to count. */
  1225. {
  1226.     LOCK_MONITOR;
  1227.  
  1228.     if (!recov_Transparent) {
  1229.     printf("Recov_NumObjects: no transparent recovery.\n");
  1230.     UNLOCK_MONITOR;
  1231.     return -1;
  1232.     }
  1233.     if (typeID < 0 || typeID >= restartTablePtr->nextTypeID) {
  1234.     return -1;
  1235.     }
  1236.  
  1237.     UNLOCK_MONITOR;
  1238.     return restartTablePtr->contents[typeID].currentNum;
  1239. }
  1240.  
  1241.  
  1242. /*
  1243.  *----------------------------------------------------------------------
  1244.  *
  1245.  * Recov_MapType --
  1246.  *
  1247.  *    Return the real type used by the kernel given the application's
  1248.  *    type number;
  1249.  *
  1250.  * Results:
  1251.  *    SUCCESS or FAILURE.  The procedure can return failure no such
  1252.  *    application type is found.
  1253.  *
  1254.  * Side effects:
  1255.  *    None.
  1256.  *
  1257.  *----------------------------------------------------------------------
  1258.  */
  1259. ReturnStatus
  1260. Recov_MapType(applicationTypeID, typeIDPtr)
  1261.     int        applicationTypeID;    /* IN: Application's type number. */
  1262.     int        *typeIDPtr;        /* OUT: Buffer to put type into. */
  1263. {
  1264.     int        i;
  1265.  
  1266.     LOCK_MONITOR;
  1267.     if (!recov_Transparent) {
  1268.     printf("Recov_MapType: no transparent recovery.\n");
  1269.     UNLOCK_MONITOR;
  1270.     return FAILURE;
  1271.     }
  1272.     for (i = 0; i < restartTablePtr->nextTypeID; i++) {
  1273.     if (restartTablePtr->contents[i].applicationTypeID ==
  1274.         applicationTypeID) {
  1275.         *typeIDPtr = i;
  1276.         UNLOCK_MONITOR;
  1277.         return SUCCESS;
  1278.     }
  1279.     }
  1280.     *typeIDPtr = -1;
  1281.  
  1282.     UNLOCK_MONITOR;
  1283.     return FAILURE;
  1284. }
  1285.  
  1286. /*
  1287.  *----------------------------------------------------------------------
  1288.  *
  1289.  * Recov_MapObjectNum --
  1290.  *
  1291.  *    Return the real object number used by the kernel given the application's
  1292.  *    object number.
  1293.  *
  1294.  * Results:
  1295.  *    SUCCESS or FAILURE.  The procedure can return failure no such
  1296.  *    application type or object number are found.
  1297.  *
  1298.  * Side effects:
  1299.  *    None.
  1300.  *
  1301.  *----------------------------------------------------------------------
  1302.  */
  1303. ReturnStatus
  1304. Recov_MapObjectNum(typeID, applicationObjectNum, objectNumPtr)
  1305.     int        typeID;            /* The real type ID of the object. */
  1306.     int        applicationObjectNum;    /* IN: Application's object num. */
  1307.     int        *objectNumPtr;        /* OUT: Buffer to put obj num into. */
  1308. {
  1309.     ObjInfo    *objInfoAddr;
  1310.     int        i;
  1311.  
  1312.     if (!recov_Transparent) {
  1313.     printf("Recov_MapObjectNum: no transparent recovery.\n");
  1314.     UNLOCK_MONITOR;
  1315.     return FAILURE;
  1316.     }
  1317.     if (typeID < 0 || typeID >= restartTablePtr->nextTypeID) {
  1318.     *objectNumPtr = -1;
  1319.     return FAILURE;
  1320.     }
  1321.     LOCK_MONITOR;
  1322.     objInfoAddr = restartTablePtr->contents[typeID].objInfoAddr;
  1323.     for (i = 0; i < restartTablePtr->contents[typeID].maxNumObjects; i++) {
  1324.     if (objInfoAddr[i].applObjNum == applicationObjectNum) {
  1325.         *objectNumPtr = i;
  1326.         UNLOCK_MONITOR;
  1327.         return SUCCESS;
  1328.     }
  1329.     }
  1330.  
  1331.     *objectNumPtr = -1;
  1332.     UNLOCK_MONITOR;
  1333.     return FAILURE;
  1334. }
  1335.  
  1336.  
  1337. /*
  1338.  *----------------------------------------------------------------------
  1339.  *
  1340.  * Recov_Checksum --
  1341.  *
  1342.  *    Compute the 16-bit one's complement of the 1's complement sum of
  1343.  *    of all words in the buffer.
  1344.  *
  1345.  *    Note: It is assumed that the length of the buffer is at most
  1346.  *    128K bytes long. It also helps if the buffer is word-aligned.
  1347.  *
  1348.  * Results:
  1349.  *    The 1's complement checksum in network byte-order.
  1350.  *
  1351.  * Side effects:
  1352.  *    None.
  1353.  *
  1354.  *----------------------------------------------------------------------
  1355.  */
  1356. unsigned short
  1357. Recov_Checksum(len, bufPtr)
  1358.     register int len;        /* The number of bytes to checksum. */
  1359.     Address bufPtr;        /* What to checksum. */
  1360. {
  1361.     register unsigned short *wordPtr = (unsigned short *) bufPtr;
  1362.     register unsigned int sum = 0;
  1363.  
  1364.     
  1365.     /*
  1366.      * The basic algorithm 16-bit 1's complement addition is 
  1367.      *  1) add the two unsigned 16-bit quantities, 
  1368.      *  2) if there was a carry out of the high-order bit, 
  1369.      *       it is added to the sum.
  1370.      * To detect a carry out of the high-order bit, the sum is stored
  1371.      * in a 32-bit word. As an optimization, we delay step 2 until
  1372.      * all the words have been added together. At that point, the
  1373.      * upper-half of the sum contains the sum of the carries from the
  1374.      * additions. This value is then added to the lower half and if that
  1375.      * operation causes a carry, then 1 is added to the sum.
  1376.      *
  1377.      * The optimization does place a limit on how many bytes can be
  1378.      * summed without causing an overflow of the 32-bit sum. In the worst
  1379.      * case, a maximum of 64K additions of 16-bit values can be added
  1380.      * without overflow.
  1381.      * 
  1382.      * The summation is done in an unrolled loop. Once we have less than 
  1383.      * 32 bytes to sum then it must be done in smaller loops.
  1384.      */
  1385.  
  1386.     while (len >= 32) {
  1387.     sum += *wordPtr++;
  1388.     sum += *wordPtr++;
  1389.     sum += *wordPtr++;
  1390.     sum += *wordPtr++;
  1391.  
  1392.     sum += *wordPtr++;
  1393.     sum += *wordPtr++;
  1394.     sum += *wordPtr++;
  1395.     sum += *wordPtr++;
  1396.  
  1397.     sum += *wordPtr++;
  1398.     sum += *wordPtr++;
  1399.     sum += *wordPtr++;
  1400.     sum += *wordPtr++;
  1401.  
  1402.     sum += *wordPtr++;
  1403.     sum += *wordPtr++;
  1404.     sum += *wordPtr++;
  1405.     sum += *wordPtr++;
  1406.  
  1407.     len -= 32;
  1408.     }
  1409.     while (len >= 2) {
  1410.     sum += *wordPtr++;
  1411.     len -= 2;
  1412.     }
  1413.  
  1414.     if (len == 1) {
  1415. #if BYTE_ORDER == LITTLE_ENDIAN
  1416.     sum += (*wordPtr) & 0x00ff;
  1417. #else
  1418.     sum += (*wordPtr) & 0xff00;
  1419. #endif
  1420.     }
  1421.  
  1422.     /*
  1423.      * The most signficant bits of "sum" contains the carries from
  1424.      * the overflow of the summing. Add this overflow back into
  1425.      * the least significant 16 bits of the sum and do it a second
  1426.      * time in case there's a carry from the first time.
  1427.      */
  1428.     if (sum > 0xffff) {
  1429.  
  1430.     sum = ((sum >> 16) & 0xffff) + (sum & 0xffff);
  1431.     /*
  1432.      * See if there was a carry from the addition. The overflow will
  1433.      * be at most 1.
  1434.      */
  1435.     if (sum > 0xffff) {
  1436.         sum++;
  1437.     }
  1438.     }
  1439.  
  1440.     return((~sum & 0xffff));
  1441. }
  1442.  
  1443. /*
  1444.  *----------------------------------------------------------------------
  1445.  *
  1446.  * Recov_Cmd --
  1447.  *
  1448.  *    Process user system call for doing recovery box operations.
  1449.  *    This is called via Sys_StatsStub and therefore has the same
  1450.  *    interface and user address pointers passed in.
  1451.  *
  1452.  * Results:
  1453.  *    SUCCESS or FAILURE.
  1454.  *
  1455.  * Side effects:
  1456.  *    May modify contents of recovery box.
  1457.  *
  1458.  *----------------------------------------------------------------------
  1459.  */
  1460. ReturnStatus
  1461. Recov_Cmd(option, argPtr)
  1462.     int        option;
  1463.     Address    argPtr;
  1464. {
  1465.     Recov_InitObjTypeArgs    initArg;
  1466.     Recov_InsertObjArgs        insertArg;
  1467.     Recov_InsertArrayArgs    insertArrayArg;
  1468.     Recov_DeleteObjArgs        deleteArg;
  1469.     Recov_UpdateObjArgs        updateArg;
  1470.     Recov_ReturnObjArgs        returnArg;
  1471.     Recov_ReturnArrayArgs    returnArrayArg;
  1472.     Recov_ReturnTableArgs    returnContentsArg;
  1473.     Recov_GetObjectSizeArgs    getObjectSizeArg;
  1474.     Recov_MapTypeArgs        mapTypeArg;
  1475.     Recov_MapObjectNumArgs    mapObjNumArg;
  1476.     ReturnStatus        status = SUCCESS;
  1477.  
  1478.     if (option != RECOV_TOGGLE_CHECKSUM &&
  1479.         option != RECOV_PRINT_REBOOT_TIMES && option != RECOV_BULK_REOPEN
  1480.         && option != RECOV_SINGLE_REOPEN &&
  1481.         option != RECOV_DO_SERVER_DRIVEN &&
  1482.         option != RECOV_NO_SERVER_DRIVEN &&
  1483.         (argPtr == (Address) NIL || argPtr == (Address) 0 ||
  1484.         argPtr == (Address) USER_NIL)) {
  1485.     return GEN_INVALID_ARG;
  1486.     }
  1487.     /* option is the command */
  1488.     switch (option) {
  1489.     case RECOV_INIT_OBJ_TYPE: {
  1490.     status = Vm_CopyIn(sizeof (initArg), argPtr,
  1491.         (Address) &initArg);
  1492.     if (status != SUCCESS) {
  1493.         break;
  1494.     }
  1495.     if (initArg.doChecksum != 0 && initArg.doChecksum != 1) {
  1496.         status = GEN_INVALID_ARG;
  1497.         break;
  1498.     }
  1499.     status = Recov_InitType(initArg.objectSize,
  1500.         initArg.maxNumObjects, initArg.applicationTypeID,
  1501.         &(initArg.objectType),
  1502.         (unsigned short (*)())initArg.doChecksum);
  1503.     if (status != SUCCESS) {
  1504.         break;
  1505.     }
  1506.     status = Vm_CopyOut(sizeof (int),
  1507.         (Address) &(initArg.objectType),
  1508.         (Address) &(((Recov_InitObjTypeArgs *)
  1509.         argPtr)->objectType));
  1510.     break;
  1511.     }
  1512.     case RECOV_INSERT_OBJ: {
  1513.     char    *objectPtr;
  1514.     int    objectSize;
  1515.  
  1516.     status = Vm_CopyIn(sizeof (insertArg), argPtr,
  1517.         (Address) &insertArg);
  1518.     if (status != SUCCESS) {
  1519.         break;
  1520.     }
  1521.     if ((insertArg.objectPtr == (Address) NIL ||
  1522.         insertArg.objectPtr == (Address) 0 ||
  1523.         insertArg.objectPtr == (Address) USER_NIL)) {
  1524.         status = GEN_INVALID_ARG;
  1525.         break;
  1526.     }
  1527.  
  1528.     objectSize = Recov_GetObjectSize(insertArg.typeID);
  1529.     if (objectSize == -1) {
  1530.         status = GEN_INVALID_ARG;
  1531.         break;
  1532.     }
  1533.     objectPtr = malloc(objectSize);
  1534.  
  1535.     status = Vm_CopyIn(objectSize, insertArg.objectPtr,
  1536.         (Address) objectPtr);
  1537.     if (status != SUCCESS) {
  1538.         free(objectPtr);
  1539.         break;
  1540.     }
  1541.     status = Recov_InsertObject(insertArg.typeID,
  1542.         (ClientData) objectPtr, insertArg.applicationObjectNum,
  1543.         &(insertArg.objectID));
  1544.     if (status != SUCCESS) {
  1545.         free(objectPtr);
  1546.         break;
  1547.     }
  1548.     status = Vm_CopyOut(sizeof (Recov_ObjectID),
  1549.         (Address) &(insertArg.objectID),
  1550.         (Address) &(((Recov_InsertObjArgs *)
  1551.         argPtr)->objectID));
  1552.     free(objectPtr);
  1553.     break;
  1554.     }
  1555.     case RECOV_INSERT_ARRAY: {
  1556.     char        *objectBuffer;
  1557.     int        objectSize;
  1558.     int        *objNumBuffer;
  1559.     Recov_ObjectID    *objIDBuffer;
  1560.     int        numObjs;
  1561.  
  1562.     status = Vm_CopyIn(sizeof (insertArrayArg), argPtr,
  1563.         (Address) &insertArrayArg);
  1564.     if (status != SUCCESS) {
  1565.         break;
  1566.     }
  1567.     if (insertArrayArg.obuffer == (Address) NIL ||
  1568.         insertArrayArg.obuffer == (Address) 0 ||
  1569.         insertArrayArg.obuffer == (Address) USER_NIL) {
  1570.         status = GEN_INVALID_ARG;
  1571.         break;
  1572.     }
  1573.     objectSize = Recov_GetObjectSize(insertArrayArg.typeID);
  1574.     if (objectSize == -1) {
  1575.         status = GEN_INVALID_ARG;
  1576.         break;
  1577.     }
  1578.     numObjs = insertArrayArg.numObjs;
  1579.     objectBuffer = malloc(objectSize * numObjs);
  1580.     status = Vm_CopyIn(objectSize * numObjs,
  1581.         (Address) insertArrayArg.obuffer,
  1582.         (Address) objectBuffer);
  1583.     if (status != SUCCESS) {
  1584.         free(objectBuffer);
  1585.         break;
  1586.     }
  1587.     if (insertArrayArg.applObjNums == (int *) NIL ||
  1588.         insertArrayArg.applObjNums == (int *) 0 ||
  1589.         insertArrayArg.applObjNums == (int *) USER_NIL) {
  1590.         objNumBuffer = (int *) NIL;
  1591.     } else {
  1592.         objNumBuffer = (int *) malloc(sizeof (int) * numObjs);
  1593.         status = Vm_CopyIn(sizeof (int) * numObjs,
  1594.             (Address) insertArrayArg.applObjNums,
  1595.             (Address) objNumBuffer);
  1596.         if (status != SUCCESS) {
  1597.         free(objectBuffer);
  1598.         free((char *) objNumBuffer);
  1599.         break;
  1600.         }
  1601.     }
  1602.     if (insertArrayArg.objIDBuffer == (Recov_ObjectID *) NIL ||
  1603.         insertArrayArg.objIDBuffer == (Recov_ObjectID *) 0 ||
  1604.         insertArrayArg.objIDBuffer ==
  1605.         (Recov_ObjectID *) USER_NIL) {
  1606.         status = GEN_INVALID_ARG;
  1607.         free(objectBuffer);
  1608.         if (objNumBuffer != (int *) NIL) {
  1609.         free((char *) objNumBuffer);
  1610.         }
  1611.         break;
  1612.     } else {
  1613.         objIDBuffer = (Recov_ObjectID *)
  1614.             malloc(sizeof (Recov_ObjectID) * numObjs);
  1615.     }
  1616.     status = Recov_InsertObjects(insertArrayArg.typeID, numObjs,
  1617.         objectBuffer, objNumBuffer, objIDBuffer);
  1618.     if (status != SUCCESS) {
  1619.         free(objectBuffer);
  1620.         if (objNumBuffer != (int *) NIL) {
  1621.         free((char *) objNumBuffer);
  1622.         }
  1623.         free((char *) objIDBuffer);
  1624.         break;
  1625.     }
  1626.     status = Vm_CopyOut(sizeof (Recov_ObjectID) * numObjs,
  1627.         (Address) objIDBuffer,
  1628.         (Address) insertArrayArg.objIDBuffer);
  1629.     free((char *) objectBuffer);
  1630.     if (objNumBuffer != (int *) NIL) {
  1631.         free((char *) objNumBuffer);
  1632.     }
  1633.     free((char *) objIDBuffer);
  1634.     break;
  1635.     }
  1636.     case RECOV_DELETE_OBJ: {
  1637.     status = Vm_CopyIn(sizeof (deleteArg), argPtr,
  1638.         (Address) &deleteArg);
  1639.     if (status != SUCCESS) {
  1640.         break;
  1641.     }
  1642.     status = Recov_DeleteObject(deleteArg.objectID);
  1643.     break;
  1644.     }
  1645.     case RECOV_UPDATE_OBJ: {
  1646.     char    *objectPtr;
  1647.     int    objectSize;
  1648.  
  1649.     status = Vm_CopyIn(sizeof (updateArg), argPtr,
  1650.         (Address) &updateArg);
  1651.     if (status != SUCCESS) {
  1652.         break;
  1653.     }
  1654.     if ((updateArg.objectPtr == (Address) NIL ||
  1655.         updateArg.objectPtr == (Address) 0 ||
  1656.         updateArg.objectPtr == (Address) USER_NIL)) {
  1657.         status = GEN_INVALID_ARG;
  1658.         break;
  1659.     }
  1660.  
  1661.     objectSize = Recov_GetObjectSize(updateArg.objectID.typeID);
  1662.     if (objectSize == -1) {
  1663.         status = GEN_INVALID_ARG;
  1664.         break;
  1665.     }
  1666.     objectPtr = malloc(objectSize);
  1667.  
  1668.     status = Vm_CopyIn(objectSize, updateArg.objectPtr,
  1669.         (Address) objectPtr);
  1670.     if (status != SUCCESS) {
  1671.         free(objectPtr);
  1672.         break;
  1673.     }
  1674.     status = Recov_UpdateObject((ClientData) objectPtr,
  1675.         updateArg.objectID);
  1676.     free(objectPtr);
  1677.     break;
  1678.     }
  1679.     case RECOV_RETURN_OBJ: {
  1680.     char    *objectPtr;
  1681.     int    objectSize;
  1682.  
  1683.     status = Vm_CopyIn(sizeof (returnArg), argPtr,
  1684.         (Address) &returnArg);
  1685.     if (status != SUCCESS) {
  1686.         break;
  1687.     }
  1688.     if (returnArg.objectPtr == (Address) NIL ||
  1689.         returnArg.objectPtr == (Address) 0 ||
  1690.         returnArg.objectPtr == (Address) USER_NIL) {
  1691.         status = GEN_INVALID_ARG;
  1692.         break;
  1693.     }
  1694.  
  1695.     objectSize = Recov_GetObjectSize(returnArg.objectID.typeID);
  1696.     if (objectSize == -1) {
  1697.         status = GEN_INVALID_ARG;
  1698.         break;
  1699.     }
  1700.     objectPtr = malloc(objectSize);
  1701.  
  1702.     status = Recov_ReturnObject((ClientData) objectPtr,
  1703.         returnArg.objectID, TRUE);
  1704.     if (status != SUCCESS) {
  1705.         free(objectPtr);
  1706.         break;
  1707.     }
  1708.     status = Vm_CopyOut(objectSize, (Address) objectPtr,
  1709.         (Address) ((Recov_ReturnObjArgs *) argPtr)->objectPtr);
  1710.     free(objectPtr);
  1711.         
  1712.     break;
  1713.     }
  1714.     case RECOV_RETURN_ARRAY: {
  1715.     char    *newobuffer;
  1716.     char    *newibuffer;
  1717.     char    *newabuffer;
  1718.  
  1719.     status = Vm_CopyIn(sizeof (returnArrayArg), argPtr,
  1720.         (Address) &returnArrayArg);
  1721.     if (status != SUCCESS) {
  1722.         break;
  1723.     }
  1724.     if ((returnArrayArg.obuffer == (Address) NIL ||
  1725.         returnArrayArg.obuffer == (Address) 0 ||
  1726.         returnArrayArg.obuffer == (Address) USER_NIL)) {
  1727.         status = GEN_INVALID_ARG;
  1728.         break;
  1729.     }
  1730.     newobuffer = malloc(returnArrayArg.olength);
  1731.  
  1732.     if ((returnArrayArg.ibuffer == (Address) NIL ||
  1733.         returnArrayArg.ibuffer == (Address) 0 ||
  1734.         returnArrayArg.ibuffer == (Address) USER_NIL)) {
  1735.         returnArrayArg.ibuffer = (Address) NIL;
  1736.         newibuffer = (char *) NIL;
  1737.     } else {
  1738.         if (returnArrayArg.ilength <= 0) {
  1739.         free(newobuffer);
  1740.         status = GEN_INVALID_ARG;
  1741.         break;
  1742.         }
  1743.         newibuffer = malloc(returnArrayArg.ilength);
  1744.     }
  1745.         
  1746.     if ((returnArrayArg.abuffer == (Address) NIL ||
  1747.         returnArrayArg.abuffer == (Address) 0 ||
  1748.         returnArrayArg.abuffer == (Address) USER_NIL)) {
  1749.         returnArrayArg.abuffer = (Address) NIL;
  1750.         newabuffer = (char *) NIL;
  1751.     } else {
  1752.         if (returnArrayArg.alength <= 0) {
  1753.         free(newobuffer);
  1754.         if (newibuffer != (char *) NIL) {
  1755.             free(newibuffer);
  1756.         }
  1757.         status = GEN_INVALID_ARG;
  1758.         break;
  1759.         }
  1760.         newabuffer = malloc(returnArrayArg.alength);
  1761.     }
  1762.         
  1763.     status = Recov_ReturnObjects(returnArrayArg.typeID,
  1764.         &returnArrayArg.olength, newobuffer,
  1765.         &returnArrayArg.ilength,
  1766.         newibuffer, &returnArrayArg.alength, newabuffer);
  1767.     if (status != SUCCESS) {
  1768.         free(newobuffer);
  1769.         if (newibuffer != (char *) NIL) {
  1770.         free(newibuffer);
  1771.         }
  1772.         if (newabuffer != (char *) NIL) {
  1773.         free(newabuffer);
  1774.         }
  1775.         break;
  1776.     }
  1777.     status = Vm_CopyOut(sizeof (int),
  1778.         (Address) &returnArrayArg.olength,
  1779.         (Address) &(((Recov_ReturnArrayArgs *)
  1780.         argPtr)->olength));
  1781.     if (status != SUCCESS) {
  1782.         free(newobuffer);
  1783.         if (newibuffer != (char *) NIL) {
  1784.         free(newibuffer);
  1785.         }
  1786.         if (newabuffer != (char *) NIL) {
  1787.         free(newabuffer);
  1788.         }
  1789.         break;
  1790.     }
  1791.     status = Vm_CopyOut(returnArrayArg.olength,
  1792.         (Address) newobuffer,
  1793.         (Address) (((Recov_ReturnArrayArgs *)
  1794.         argPtr)->obuffer));
  1795.  
  1796.     if (status != SUCCESS) {
  1797.         free(newobuffer);
  1798.         if (newibuffer != (char *) NIL) {
  1799.         free(newibuffer);
  1800.         }
  1801.         if (newabuffer != (char *) NIL) {
  1802.         free(newabuffer);
  1803.         }
  1804.         break;
  1805.     }
  1806.     if (newibuffer != (char *) NIL) {
  1807.         status = Vm_CopyOut(sizeof (int),
  1808.             (Address) &returnArrayArg.ilength, (Address)
  1809.             &(((Recov_ReturnArrayArgs *) argPtr)->ilength));
  1810.         if (status != SUCCESS) {
  1811.         free(newobuffer);
  1812.         free(newibuffer);
  1813.         if (newabuffer != (char *) NIL) {
  1814.             free(newabuffer);
  1815.         }
  1816.         break;
  1817.         }
  1818.         status = Vm_CopyOut(returnArrayArg.ilength,
  1819.             (Address) newibuffer,
  1820.             (Address)
  1821.             (((Recov_ReturnArrayArgs *) argPtr)->ibuffer));
  1822.         if (status != SUCCESS) {
  1823.         free(newobuffer);
  1824.         free(newibuffer);
  1825.         if (newabuffer != (char *) NIL) {
  1826.             free(newabuffer);
  1827.         }
  1828.         break;
  1829.         }
  1830.     }
  1831.     if (newabuffer != (char *) NIL) {
  1832.         status = Vm_CopyOut(sizeof (int),
  1833.             (Address) &returnArrayArg.alength, (Address)
  1834.             &(((Recov_ReturnArrayArgs *) argPtr)->alength));
  1835.         if (status != SUCCESS) {
  1836.         free(newobuffer);
  1837.         if (newibuffer != (char *) NIL) {
  1838.             free(newibuffer);
  1839.         }
  1840.         free(newabuffer);
  1841.         break;
  1842.         }
  1843.         status = Vm_CopyOut(returnArrayArg.alength,
  1844.             (Address) newabuffer,
  1845.             (Address)
  1846.             (((Recov_ReturnArrayArgs *) argPtr)->abuffer));
  1847.     }
  1848.  
  1849.     free(newobuffer);
  1850.     if (newibuffer != (char *) NIL) {
  1851.         free(newibuffer);
  1852.     }
  1853.     if (newabuffer != (char *) NIL) {
  1854.         free(newabuffer);
  1855.     }
  1856.     break;
  1857.     }
  1858.     case RECOV_RETURN_CONTENTS: {
  1859.     char    *newbuffer;
  1860.     int    length;
  1861.  
  1862.     status = Vm_CopyIn(sizeof (returnContentsArg), argPtr,
  1863.         (Address) &returnContentsArg);
  1864.     if (status != SUCCESS) {
  1865.         break;
  1866.     }
  1867.     if ((returnContentsArg.buffer == (Address) NIL ||
  1868.         returnContentsArg.buffer == (Address) 0 ||
  1869.         returnContentsArg.buffer == (Address) USER_NIL)) {
  1870.         status = GEN_INVALID_ARG;
  1871.         break;
  1872.     }
  1873.     length = returnContentsArg.length;
  1874.     newbuffer = malloc(length);
  1875.     status = Recov_ReturnContents(&length, newbuffer);
  1876.     if (status != SUCCESS) {
  1877.         free(newbuffer);
  1878.         break;
  1879.     }
  1880.     status = Vm_CopyOut(sizeof (int), (Address) &length,
  1881.         (Address) &(((Recov_ReturnTableArgs *)
  1882.         argPtr)->length));
  1883.     if (status != SUCCESS) {
  1884.         free(newbuffer);
  1885.         break;
  1886.     }
  1887.     status = Vm_CopyOut(length, (Address) newbuffer,
  1888.         (Address) (((Recov_ReturnTableArgs *) argPtr)->buffer));
  1889.     break;
  1890.     }
  1891.     case RECOV_GET_OBJECT_SIZE: {
  1892.     status = Vm_CopyIn(sizeof (getObjectSizeArg), argPtr,
  1893.         (Address) &getObjectSizeArg);
  1894.     if (status != SUCCESS) {
  1895.         break;
  1896.     }
  1897.  
  1898.     getObjectSizeArg.objectSize =
  1899.         Recov_GetObjectSize(getObjectSizeArg.typeID);
  1900.     if (getObjectSizeArg.objectSize == -1) {
  1901.         status = GEN_INVALID_ARG;
  1902.         break;
  1903.     }
  1904.     status = Vm_CopyOut(sizeof (getObjectSizeArg),
  1905.         (Address) &getObjectSizeArg, argPtr);
  1906.     break;
  1907.     }
  1908.     case RECOV_MAP_TYPE: {
  1909.     status = Vm_CopyIn(sizeof (mapTypeArg), argPtr,
  1910.         (Address) &mapTypeArg);
  1911.     if (status != SUCCESS) {
  1912.         break;
  1913.     }
  1914.     status = Recov_MapType(mapTypeArg.applicationTypeID,
  1915.         &(mapTypeArg.typeID));
  1916.     if (status != SUCCESS) {
  1917.         break;
  1918.     }
  1919.     status = Vm_CopyOut(sizeof (mapTypeArg),
  1920.         (Address) &mapTypeArg, argPtr);
  1921.     break;
  1922.     }
  1923.     case RECOV_MAP_OBJ_NUM: {
  1924.     status = Vm_CopyIn(sizeof (mapObjNumArg), argPtr,
  1925.         (Address) &mapObjNumArg);
  1926.     if (status != SUCCESS) {
  1927.         break;
  1928.     }
  1929.     status = Recov_MapObjectNum(mapObjNumArg.realTypeID,
  1930.         mapObjNumArg.applicationObjectNum,
  1931.         &(mapObjNumArg.realObjectNum));
  1932.     if (status != SUCCESS) {
  1933.         break;
  1934.     }
  1935.     status = Vm_CopyOut(sizeof (mapObjNumArg),
  1936.         (Address) &mapObjNumArg, argPtr);
  1937.     break;
  1938.     }
  1939.     case RECOV_TOGGLE_CHECKSUM: {
  1940.     Recov_ToggleChecksum((int) argPtr);
  1941.     status = SUCCESS;
  1942.     break;
  1943.     }
  1944.     case RECOV_BULK_REOPEN: {
  1945.     recov_BulkHandles = TRUE;
  1946.     status = SUCCESS;
  1947.     break;
  1948.     }
  1949.     case RECOV_SINGLE_REOPEN: {
  1950.     recov_BulkHandles = FALSE;
  1951.     status = SUCCESS;
  1952.     break;
  1953.     }
  1954.     case RECOV_IGNORE_CLEAN: {
  1955.     if (recov_SkipCleanFiles) {
  1956.         printf("Cannot both skip and ignore reopening clean files.\n");
  1957.         status = FAILURE;
  1958.     } else {
  1959.         recov_IgnoreCleanFiles = TRUE;
  1960.         status = SUCCESS;
  1961.     }
  1962.     break;
  1963.     }
  1964.     case RECOV_REOPEN_CLEAN: {
  1965.     recov_IgnoreCleanFiles = FALSE;
  1966.     recov_SkipCleanFiles = FALSE;
  1967.     status = SUCCESS;
  1968.     break;
  1969.     }
  1970.     case RECOV_SKIP_CLEAN: {
  1971.     if (recov_IgnoreCleanFiles) {
  1972.         printf("Cannot both skip and ignore reopening clean files.\n");
  1973.         status = FAILURE;
  1974.     } else {
  1975.         recov_SkipCleanFiles = TRUE;
  1976.         status = SUCCESS;
  1977.     }
  1978.     break;
  1979.     }
  1980.     case RECOV_DO_SERVER_DRIVEN: {
  1981.     recov_ClientIgnoreServerDriven = FALSE;
  1982.     printf("Client is now responding to server-driven recovery.\n");
  1983.     status = SUCCESS;
  1984.     break;
  1985.     }
  1986.     case RECOV_NO_SERVER_DRIVEN: {
  1987.     recov_ClientIgnoreServerDriven = TRUE;
  1988.     printf("Client is now ignoring server-driven recovery.\n");
  1989.     status = SUCCESS;
  1990.     break;
  1991.     }
  1992.     case RECOV_PRINT_SIZE: {
  1993.     int    objSize;
  1994.  
  1995.     objSize = (int) argPtr;
  1996.     Recov_PrintSpace(objSize);
  1997.     status = SUCCESS;
  1998.     break;
  1999.     }
  2000.     default:
  2001.     status = GEN_INVALID_ARG;
  2002.     break;
  2003.     }
  2004.  
  2005.     return status;
  2006. }
  2007.